/*
 * 1.DOM1
 * 2.DOM2
 * 3.DOM3
 */

/*
 * 1.DOM1
 */
//Node 接口(类型)，IE不可访问到这个类型
var element_node = Node.ELEMENT_NODE(1);
var attribude_node = Node.ATTRIBUDE_NODE(2);
var text_node = Node.TEXT_NODE(3);
var cdata_section_node = Node.CDATA_SECTION_NODE(4);
var entity_reference_node=Node.ENTITYREFERENCE_NODE(5);
var entity_node=Node.ENTITY_NODE(6);
var processing_instruction_node=Node.PROCESSING_INSTRUCTION_NODE(7);
var comment_node=Node.COMMENT_NODE(8);
var document_node=Node.DOCUMENT_NODE(9);
var document_type_node=Node.DOCUMENT_TYPE_NODE(10);
var document_fragent_node=Node.DOCUMENT_FRAGENT_NODE(11);
var notation_node=Node.NOTATION_NODE(12);
//每个节点都有nodeType属性
var nodename=someNode.nodeName,//获取标签名
    nodetype=someNode.nodeType,//标签类型
    nodevalue=someNode.nodeValue;//nodeValue的值始终是null


//节点关系
//childNodes 属性 对象是NodeList
//兄弟节点：previousSibling and nextSibling
//父节点：firstChild and lastChild
//hasChildNodes()
//ownerDocument 该属性指向表示整个文档的文档节点


//操作节点
//appendChild() 在 childNodes 列表末尾添加一个节点
//insertBefore() 把节点放在 childNodes 列表中的某个特定的位置上
//replaceChild() 接受两个参数：要插入的节点 和 要替换的节点
//removeChild() 即要移除的节点


//其他方法
//cloneNode() 创建完全相同的副本，参数为布尔值
//normalize() 处理文档树中的文本节点


//Document 类型
//document 对象是 HTMLDocument 的一个实例。而且，document 对象是 window 对象的一个属性
//Document 节点具有下列特征
// 1.nodeType 的值为 9
// 2.nodeName 的值为 "#document"
// 3.nodeValue 的值为 null
// 4.parentNode 的值为 null
// 5.ownerDocument 的值为 null
// 6.其子节点可能是一个DocumentType(最多一个)、Element(最多一个)、ProcessingInstruction或Comment
  //取得完整的域名
  var url = document.URL;
  //取得域名
  var domain =document.domain;
  //取得来源页面的URL
  var referrer = document.referrer;
//查找元素
//getdocumentById() and getElementByTagName() and getElementByName()
//特殊集合：document.anchors / document.applets / document.forms / document.images / document.links
//DOM 一致性检测
   var hasXmlDom =  document.implementation.hasFeature("XML","1.0");
//文档写入：write()、writeln()、open()、close()


//Element 类型
//Element 类型用于表现 XML 或 HTML 元素，节点如下
// 1.nodeType 的值为 1
// 2.nodeName(tagName) 的值为元素的标签名
   if (element.tagName.toLowerCase()=="div") {} //OK
// 3.nodeValue 的值为 null
// 4.parentNode 可能是 Document 或 Element
// 5.其子节点可能是：Element、text、Comment、processingInstruction、CDATASection 或 EntityReference
//
//HTML 元素：id、title、lang、dir(ltr)、className
//取得特性：getAttribute()、setAttribute()、removeAttribute()。自定义特性应该加上 data- 前缀一遍验证
//attibutes:getNameItem(name)、removeNameItem(name)、setNametItem(node)、item(pos)
//创建元素：document.createElement()
//
//text 类型：特点如下
// nodeType 的值为 3
// nodeName 的值为 "#text"
// nodeValue 的值为节点所包含的文本
// parentNode 是一个Element
// 不支持（没有）子节点
// 操作节点中的文本的方法
//  appendData(text)：将 text 添加到节点的末尾
//  deleteData(offset,count)：从 offset 指定的位置开始删除 count 个字符
//  insertData(offset,text)：从 offset 指定的位置插入 text
//  replaceData(offset,count,text)：用 text 替换从 offset 指定的位置开始到 offset+count 为止处的文本
//  splitText(offset)：从 offset 指定的位置将当前文本节点分成两个文本节点
//  substringData(offset,count)：提取从 offset 指定的位置开始到 offset+count 为止的字符串
//
//创建文本节点：document.createTextNode()
//规范文本节点：normalize()
//分割文本节点：splitText()
//
//Comment 类型
// nodeType 的值为 8
// nodeName 的值为 "#comment"
// nodeValue 的值是注释的内容
// parentNode 可能是 Document 或 Element
// 不支持（没有）子节点
//comment.data 、 document.createComment()
//
//CDATASection 类型：针对 XML 的文档
// nodeType 的值为 4
// nodeName 的值为 "#cdata-section"
// nodeValue 的值是 CDATA 区域中的内容
// parentNode 可能是 Document 或 Element
// 不支持（没有）子节点
//
//DocumentType 类型：不常用
// nodeType 的值为 10
// nodeName 的值为 doctype 的名称
// nodeValue 的值为 null
// parentNode 是 Document
// 不支持（没有）子节点
//
//DocumentFragment 类型：在文档中没有对应的标记
// nodeType 的值我 11
// nodeName 的值为 "#document-fragment"
// nodeValue 的值为 null
// parentNode 的值为 null
// 子节点可以是 Element、processingInstruction、Comment、Text、CDATASection 或者 EntityReference
//document.createDocumentFragment()
//
//Attr 类型 特征
// nodeType 的值为 2
// nodeName 的值是特性的名称
// nodeValue 的值是特性的值
// parentNode 的值为 null
// 在 HTML 中不支持（没有）子节点
// 在 XML 中子节点可以是 Text 或 EntityReference
//Attr 有三个属性：name、value 和 specified
//document.createAttribute()


//选择符API
//querySelector() 、querySelectorAll() 、{ matchesSection()：接收一个参数，即 CSS 选择符，返回布尔值 }
//
//元素遍历：Element Traversal API 为 DOM 添加了 5 个属性
// childElementCount：返回子元素（不包括文本节点和注释）的个数
// firstElementChild：指向第一个子元素；firstChild 的元素
// lastElementChild：指向最后一个子元素
// previousElementSibling：指向前一个同辈元素
// nextElementSibling：指向后一个同辈元素
//
//HTML5
//getElementByClassName()
//classList 属性：add(value)、contains(value)、remove(value)、toggle(value)
// 焦点管理
//document.activeElement 、document.hasFocus()
// HTMLDocument
//document.readState == loading or document.readyState == complete
//兼容模式：document.compatMode == "CSS1Compat"
//document.head
//
//字符集属性：charset 、defaultCharset
//
//自定义数据属性：dataset
//
//插入标记
//innerHTML
//outerHTML
//insertAbjacentHTML(" ","<p>hello word</p>"); beforegegin 、 afterbegin 、beforeend 、 afterend
//
//scrollIntoView():document.forms[0].scrollIntoView()
//
//文档模式：documen.documentMode
//
//children 属性
//contains() 方法与 compareDocumentPosition() 方法确定节点之间的关系
//
//插入文本：innerText属性 、outerText属性
//
//滚动：scrollIntoView() 、scrollIntoViewIfNeeded(alignCenter) 、scrollByLines(lineCount) 、scrollByPages(pageCount)


/*
 * 2.DOM2
 * 3.DOM3
 */
//命名空间：xmlns
//Node 类型的变化
//

// 一、DOM 概述
// 1、DOM：DOM 是 JavaScript 操作网页的接口，全称为“文档对象模型”（Document Object Model）。它的作用是将网页转为一个 JavaScript 对象，从而可以用脚本进行各种操作（比如增删内容）。
// 2、节点：DOM 的最小组成单位叫做节点（node）。文档的树形结构（DOM 树），就是由各种不同类型的节点组成。每个节点可以看作是文档树的一片叶子。
// 节点的类型有七种。
//     Document：整个文档树的顶层节点
//     DocumentType：doctype标签（比如<!DOCTYPE html>）
//     Element：网页的各种HTML标签（比如<body>、<a>等）
//     Attr：网页元素的属性（比如class="right"）
//     Text：标签之间或标签包含的文本
//     Comment：注释
//     DocumentFragment：文档的片段
// 浏览器提供一个原生的节点对象Node，上面这七种节点都继承了Node，因此具有一些共同的属性和方法。
// 3、节点树 ：一个文档的所有节点，按照所在的层级，可以抽象成一种树状结构。这种树状结构就是 DOM 树。它有一个顶层节点，下一层都是顶层节点的子节点，然后子节点又有自己的子节点，就这样层层衍生出一个金字塔结构，又像一棵树。
// 浏览器原生提供document节点，代表整个文档。
// 文档的第一层有两个节点，第一个是文档类型节点（<!doctype html>），第二个是 HTML 网页的顶层容器标签<html>。后者构成了树结构的根节点（root node），其他 HTML 标签节点都是它的下级节点。
// 除了根节点，其他节点都有三种层级关系。
//     父节点关系（parentNode）：直接的那个上级节点
//     子节点关系（childNodes）：直接的下级节点
//     同级节点关系（sibling）：拥有同一个父节点的节点
// DOM 提供操作接口，用来获取这三种关系的节点。比如，子节点接口包括firstChild（第一个子节点）和lastChild（最后一个子节点）等属性，同级节点接口包括nextSibling（紧邻在后的那个同级节点）和previousSibling（紧邻在前的那个同级节点）属性。

// 二、Node 接口
// 1、属性
  // 1.1、Node.prototype.nodeType：nodeType属性返回一个整数值，表示节点的类型。document.nodeType // 9
  // Node 对象定义了几个常量，对应这些类型值。
  // document.nodeType === Node.DOCUMENT_NODE // true
  // 上面代码中，文档节点的nodeType属性等于常量Node.DOCUMENT_NODE。
  // 不同节点的nodeType属性值和对应的常量如下。
  //     文档节点（document）：9，对应常量Node.DOCUMENT_NODE
  //     元素节点（element）：1，对应常量Node.ELEMENT_NODE
  //     属性节点（attr）：2，对应常量Node.ATTRIBUTE_NODE
  //     文本节点（text）：3，对应常量Node.TEXT_NODE
  //     文档片断节点（DocumentFragment）：11，对应常量Node.DOCUMENT_FRAGMENT_NODE
  //     文档类型节点（DocumentType）：10，对应常量Node.DOCUMENT_TYPE_NODE
  //     注释节点（Comment）：8，对应常量Node.COMMENT_NODE
  // 确定节点类型时，使用nodeType属性是常用方法。
  // var node = document.documentElement.firstChild;
  // if (node.nodeType === Node.ELEMENT_NODE) {
  //   console.log('该节点是元素节点');
  // }
  // 1.2、Node.prototype.nodeName：Node.prototype.nodeName；nodeName属性返回节点的名称。
  // // HTML 代码如下
  // // <div id="d1">hello world</div>
  // var div = document.getElementById('d1');
  // div.nodeName // "DIV"
  // 不同节点的nodeName属性值如下。
  //     文档节点（document）：#document
  //     元素节点（element）：大写的标签名
  //     属性节点（attr）：属性的名称
  //     文本节点（text）：#text
  //     文档片断节点（DocumentFragment）：#document-fragment
  //     文档类型节点（DocumentType）：文档的类型
  //     注释节点（Comment）：#comment
  // 1.3、Node.prototype.nodeValue：nodeValue属性返回一个字符串，表示当前节点本身的文本值，该属性可读写。
  // 只有文本节点（text）、注释节点（comment）和属性节点（attr）有文本值，因此这三类节点的nodeValue可以返回结果，其他类型的节点一律返回null。同样的，也只有这三类节点可以设置nodeValue属性的值，其他类型的节点设置无效。
  // 1.4、Node.prototype.textContent：textContent属性返回当前节点和它的所有后代节点的文本内容。document.getElementById('divA').textContent
  // 1.5、Node.prototype.baseURI：baseURI属性返回一个字符串，表示当前网页的绝对路径。浏览器根据这个属性，计算网页上的相对路径的 URL。该属性为只读。document.baseURI
  // 该属性的值一般由当前网址的 URL（即window.location属性）决定，但是可以使用 HTML 的<base>标签，改变该属性的值。
  // <base href="http://www.example.com/page.html">
  // 设置了以后，baseURI属性就返回<base>标签设置的值。
  // 1.6、Node.prototype.ownerDocument：Node.ownerDocument属性返回当前节点所在的顶层文档对象，即document对象。
  // 1.7、Node.prototype.nextSibling：Node.nextSibling属性返回紧跟在当前节点后面的第一个同级节点。如果当前节点后面没有同级节点，则返回null。
  // // HTML 代码如下
  // // <div id="d1">hello</div><div id="d2">world</div>
  // var d1 = document.getElementById('d1');
  // var d2 = document.getElementById('d2');
  // d1.nextSibling === d2 // true
  // 1.8、Node.prototype.previousSibling：previousSibling属性返回当前节点前面的、距离最近的一个同级节点。如果当前节点前面没有同级节点，则返回null。
  // 1.9、Node.prototype.parentNode：parentNode属性返回当前节点的父节点。对于一个节点来说，它的父节点只可能是三种类型：元素节点（element）、文档节点（document）和文档片段节点（documentfragment）
  // 1.10、Node.prototype.parentElement：parentElement属性返回当前节点的父元素节点。如果当前节点没有父节点，或者父节点类型不是元素节点，则返回null。
  // 1.11、Node.prototype.firstChild，Node.prototype.lastChild：firstChild属性返回当前节点的第一个子节点，如果当前节点没有子节点，则返回null。
  // 注意，firstChild返回的除了元素节点，还可能是文本节点或注释节点。
  // lastChild属性返回当前节点的最后一个子节点，如果当前节点没有子节点，则返回null。用法与firstChild属性相同
  // 1.12、Node.prototype.childNodes：childNodes属性返回一个类似数组的对象（NodeList集合），成员包括当前节点的所有子节点。
  // var children = document.querySelector('ul').childNodes;
  // 1.13、Node.prototype.isConnected：isConnected属性返回一个布尔值，表示当前节点是否在文档之中。
// 2、方法
  // 2.1、Node.prototype.appendChild(): appendChild()方法接受一个节点对象作为参数，将其作为最后一个子节点，插入当前节点。该方法的返回值就是插入文档的子节点。
  // var p = document.createElement('p');
  // document.body.appendChild(p);
  // 如果appendChild()方法的参数是DocumentFragment节点，那么插入的是DocumentFragment的所有子节点，而不是DocumentFragment节点本身。返回值是一个空的DocumentFragment节点。
  // 2.2、Node.prototype.hasChildNodes()：hasChildNodes方法返回一个布尔值，表示当前节点是否有子节点。
  // 注意，子节点包括所有类型的节点，并不仅仅是元素节点。哪怕节点只包含一个空格，hasChildNodes方法也会返回true。
  // 判断一个节点有没有子节点，有许多种方法，下面是其中的三种。
  //   node.hasChildNodes()
  //   node.firstChild !== null
  //   node.childNodes && node.childNodes.length > 0
  // hasChildNodes方法结合firstChild属性和nextSibling属性，可以遍历当前节点的所有后代节点。
  // 2.3、Node.prototype.cloneNode()：cloneNode方法用于克隆一个节点。它接受一个布尔值作为参数，表示是否同时克隆子节点。它的返回值是一个克隆出来的新节点。
  // var cloneUL = document.querySelector('ul').cloneNode(true);
  // 该方法有一些使用注意点。
  // （1）克隆一个节点，会拷贝该节点的所有属性，但是会丧失addEventListener方法和on-属性（即node.onclick = fn），添加在这个节点上的事件回调函数。
  // （2）该方法返回的节点不在文档之中，即没有任何父节点，必须使用诸如Node.appendChild这样的方法添加到文档之中。
  // （3）克隆一个节点之后，DOM 有可能出现两个有相同id属性（即id="xxx"）的网页元素，这时应该修改其中一个元素的id属性。如果原节点有name属性，可能也需要修改。
  // 2.4、Node.prototype.insertBefore()：insertBefore方法用于将某个节点插入父节点内部的指定位置。
  // insertBefore方法接受两个参数，第一个参数是所要插入的节点newNode，第二个参数是父节点parentNode内部的一个子节点referenceNode。newNode将插在referenceNode这个子节点的前面。返回值是插入的新节点newNode。
  // 2.5、Node.prototype.removeChild()：removeChild方法接受一个子节点作为参数，用于从当前节点移除该子节点。返回值是移除的子节点。
  // 2.6、Node.prototype.replaceChild()：replaceChild方法用于将一个新的节点，替换当前节点的某一个子节点。
  // 2.7、Node.prototype.contains()：contains方法返回一个布尔值，表示参数节点是否满足以下三个条件之一。
  //   参数节点为当前节点。
  //   参数节点为当前节点的子节点。
  //   参数节点为当前节点的后代节点。
  // 2.8、Node.prototype.compareDocumentPosition()：compareDocumentPosition方法的用法，与contains方法完全一致，返回一个六个比特位的二进制值，表示参数节点与当前节点的关系。
  // 2.9、Node.prototype.isEqualNode()，Node.prototype.isSameNode()：
  //   isEqualNode方法返回一个布尔值，用于检查两个节点是否相等。所谓相等的节点，指的是两个节点的类型相同、属性相同、子节点相同。
  //   isSameNode方法返回一个布尔值，表示两个节点是否为同一个节点。
  // 2.10、Node.prototype.normalize()：normalize方法用于清理当前节点内部的所有文本节点（text）。它会去除空的文本节点，并且将毗邻的文本节点合并成一个，也就是说不存在空的文本节点，以及毗邻的文本节点。
  // 2.11、Node.prototype.getRootNode()：getRootNode()方法返回当前节点所在文档的根节点document，与ownerDocument属性的作用相同。该方法可用于document节点自身，这一点与document.ownerDocument不同。

// 三、NodeList 接口，HTMLCollection 接口
// 1、NodeList 接口：
  // 1.1、概述 ：NodeList实例是一个类似数组的对象，它的成员是节点对象。通过以下方法可以得到NodeList实例。
  //   Node.childNodes
  //   document.querySelectorAll()等节点搜索方法
    // NodeList实例很像数组，可以使用length属性和forEach方法。但是，它不是数组，不能使用pop或push之类数组特有的方法。
  // 1.2、NodeList.prototype.length：length属性返回 NodeList 实例包含的节点数量。
  // 1.3、NodeList.prototype.forEach()：forEach方法用于遍历 NodeList 的所有成员。它接受一个回调函数作为参数，每一轮遍历就执行一次这个回调函数，用法与数组实例的forEach方法完全一致。
  // 1.4、NodeList.prototype.item()：item方法接受一个整数值作为参数，表示成员的位置，返回该位置上的成员。
  // 1.5、NodeList.prototype.keys()，NodeList.prototype.values()，NodeList.prototype.entries()：这三个方法都返回一个 ES6 的遍历器对象，可以通过for...of循环遍历获取每一个成员的信息。
  //   区别在于，keys()返回键名的遍历器，values()返回键值的遍历器，entries()返回的遍历器同时包含键名和键值的信息。
// 2、HTMLCollection 接口
//   2.1、概述：HTMLCollection是一个节点对象的集合，只能包含元素节点（element），不能包含其他类型的节点。它的返回值是一个类似数组的对象，但是与NodeList接口不同，HTMLCollection没有forEach方法，只能使用for循环遍历。
  // 2.2、HTMLCollection.prototype.length：length属性返回HTMLCollection实例包含的成员数量。
  //   document.links.length 
  // 2.3、HTMLCollection.prototype.item()：item方法接受一个整数值作为参数，表示成员的位置，返回该位置上的成员。
  //   var c = document.images;
  //   var img0 = c.item(0);
  // 2.4、HTMLCollection.prototype.namedItem()：namedItem方法的参数是一个字符串，表示id属性或name属性的值，返回对应的元素节点。如果没有对应的节点，则返回null。
  //   // HTML 代码如下
  //   // <img id="pic" src="http://example.com/foo.jpg">
  //   var pic = document.getElementById('pic');
  //   document.images.namedItem('pic') === pic // true

// 四、ParentNode 接口，ChildNode 接口
// ParentNode接口表示当前节点是一个父节点，提供一些处理子节点的方法。ChildNode接口表示当前节点是一个子节点，提供一些相关方法。
// 1、ParentNode 接口：如果当前节点是父节点，就会混入了（mixin）ParentNode接口。由于只有元素节点（element）、文档节点（document）和文档片段节点（documentFragment）拥有子节点，因此只有这三类节点会拥有ParentNode接口。
  // 1.1、ParentNode.children：children属性返回一个HTMLCollection实例，成员是当前节点的所有元素子节点。该属性只读。
  // 1.2、ParentNode.firstElementChild：firstElementChild属性返回当前节点的第一个元素子节点。如果没有任何元素子节点，则返回null。
  // 1.3、ParentNode.lastElementChild：lastElementChild属性返回当前节点的最后一个元素子节点，如果不存在任何元素子节点，则返回null。
  // 1.4、ParentNode.childElementCount：childElementCount属性返回一个整数，表示当前节点的所有元素子节点的数目。如果不包含任何元素子节点，则返回0。
  // 1.5、ParentNode.append()，ParentNode.prepend()：append方法为当前节点追加一个或多个子节点，位置是最后一个元素子节点的后面。
// 2、ChildNode 接口：如果一个节点有父节点，那么该节点就拥有了ChildNode接口。
//   2.1、ChildNode.remove()：remove方法用于从父节点移除当前节点。
//   2.2、ChildNode.before()，ChildNode.after()：before方法用于在当前节点的前面，插入一个或多个同级节点。两者拥有相同的父节点。注意，该方法不仅可以插入元素节点，还可以插入文本节点。
//   2.3、ChildNode.replaceWith()：replaceWith方法使用参数节点，替换当前节点。参数可以是元素节点，也可以是文本节点。

// 五、Document 节点
// 1、概述：document节点对象代表整个文档，每张网页都有自己的document对象。window.document属性就指向这个对象。只要浏览器开始载入 HTML 文档，该对象就存在了，可以直接使用。
// document对象有不同的办法可以获取。
//     正常的网页，直接使用document或window.document。
//     iframe框架里面的网页，使用iframe节点的contentDocument属性。
//     Ajax 操作返回的文档，使用XMLHttpRequest对象的responseXML属性。
//     内部节点的ownerDocument属性。
// document对象继承了EventTarget接口和Node接口，并且混入（mixin）了ParentNode接口。这意味着，这些接口的方法都可以在document对象上调用。除此之外，document对象还有很多自己的属性和方法。
// 2、属性
  // 2.1、快捷方式属性：以下属性是指向文档内部的某个节点的快捷方式
  // （1）、document.defaultView：document.defaultView属性返回document对象所属的window对象。如果当前文档不属于window对象，该属性返回null。
  // （2）、document.doctype：对于 HTML 文档来说，document对象一般有两个子节点。第一个子节点是document.doctype，指向<DOCTYPE>节点，即文档类型（Document Type Declaration，简写DTD）节点。HTML 的文档类型节点，一般写成<!DOCTYPE html>。如果网页没有声明 DTD，该属性返回null。
  // （3）、document.documentElement：document.documentElement属性返回当前文档的根元素节点（root）。它通常是document节点的第二个子节点，紧跟在document.doctype节点后面。HTML网页的该属性，一般是<html>节点。
  // （4）、document.body，document.head：document.body属性指向<body>节点，document.head属性指向<head>节点。
  // （5）、document.scrollingElement：document.scrollingElement属性返回文档的滚动元素。也就是说，当文档整体滚动时，到底是哪个元素在滚动。
  // （6）、document.activeElement：document.activeElement属性返回获得当前焦点（focus）的 DOM 元素。通常，这个属性返回的是<input>、<textarea>、<select>等表单元素，如果当前没有焦点元素，返回<body>元素或null。
  // （7）、document.fullscreenElement：document.fullscreenElement属性返回当前以全屏状态展示的 DOM 元素。如果不是全屏状态，该属性返回null。
  // 2.2、节点集合属性：以下属性返回一个HTMLCollection实例，表示文档内部特定元素的集合。这些集合都是动态的，原节点有任何变化，立刻会反映在集合中。
  // （1）、document.links：document.links属性返回当前文档所有设定了href属性的<a>及<area>节点。
  // （2）、document.forms：document.forms属性返回所有<form>表单节点。
  // （3）、document.images：document.images属性返回页面所有<img>图片节点。
  // （4）、document.embeds，document.plugins：document.embeds属性和document.plugins属性，都返回所有<embed>节点。
  // （5）、document.scripts：document.scripts属性返回所有<script>节点。
  // （6）、document.styleSheets：document.styleSheets属性返回文档内嵌或引入的样式表集合，详细介绍请看《CSS 对象模型》一章。
  // （7）、小结：除了document.styleSheets，以上的集合属性返回的都是HTMLCollection实例。
  // 2.3、文档静态信息属性：以下属性返回文档信息
  // （1）、document.documentURI，document.URL：document.documentURI属性和document.URL属性都返回一个字符串，表示当前文档的网址。不同之处是它们继承自不同的接口，documentURI继承自Document接口，可用于所有文档；URL继承自HTMLDocument接口，只能用于 HTML 文档。
  // （2）、document.domain：document.domain属性返回当前文档的域名，不包含协议和端口。比如，网页的网址是http://www.example.com:80/hello.html，那么document.domain属性就等于www.example.com。如果无法获取域名，该属性返回null。
  // （3）、document.location：Location对象是浏览器提供的原生对象，提供 URL 相关的信息和操作方法。通过window.location和document.location属性，可以拿到这个对象。
  // （4）、document.lastModified：document.lastModified属性返回一个字符串，表示当前文档最后修改的时间。不同浏览器的返回值，日期格式是不一样的。
  // （5）、document.title：document.title属性返回当前文档的标题。默认情况下，返回<title>节点的值。但是该属性是可写的，一旦被修改，就返回修改后的值。
  // （6）、document.characterSet：document.characterSet属性返回当前文档的编码，比如UTF-8、ISO-8859-1等等。
  // （7）、document.referrer：document.referrer属性返回一个字符串，表示当前文档的访问者来自哪里。
  // （8）、document.dir：document.dir返回一个字符串，表示文字方向。它只有两个可能的值：rtl表示文字从右到左，阿拉伯文是这种方式；ltr表示文字从左到右，包括英语和汉语在内的大多数文字采用这种方式。
  // （9）、document.compatMode：compatMode属性返回浏览器处理文档的模式，可能的值为BackCompat（向后兼容模式）和CSS1Compat（严格模式）。
  // 2.4、文档状态属性
  // （1）、document.hidden：document.hidden属性返回一个布尔值，表示当前页面是否可见。如果窗口最小化、浏览器切换了 Tab，都会导致导致页面不可见，使得document.hidden返回true。
  // （2）、document.visibilityState：document.visibilityState返回文档的可见状态。
  //   它的值有四种可能。
  //     visible：页面可见。注意，页面可能是部分可见，即不是焦点窗口，前面被其他窗口部分挡住了。
  //     hidden：页面不可见，有可能窗口最小化，或者浏览器切换到了另一个 Tab。
  //     prerender：页面处于正在渲染状态，对于用户来说，该页面不可见。
  //     unloaded：页面从内存里面卸载了。
  //   这个属性可以用在页面加载时，防止加载某些资源；或者页面不可见时，停掉一些页面功能。
  // （3）、document.readyState：document.readyState属性返回当前文档的状态，共有三种可能的值。
  //   loading：加载 HTML 代码阶段（尚未完成解析）
  //   interactive：加载外部资源阶段
  //   complete：加载完成
  //   * 这个属性变化的过程如下。
  //   浏览器开始解析 HTML 文档，document.readyState属性等于loading。
  //   浏览器遇到 HTML 文档中的<script>元素，并且没有async或defer属性，就暂停解析，开始执行脚本，这时document.readyState属性还是等于loading。
  //   HTML 文档解析完成，document.readyState属性变成interactive。
  //   浏览器等待图片、样式表、字体文件等外部资源加载完成，一旦全部加载完成，document.readyState属性变成complete。
  // 2.5、document.cookie：document.cookie属性用来操作浏览器 Cookie，详见《浏览器模型》部分的《Cookie》章节。
  // 2.6、document.designMode：document.designMode属性控制当前文档是否可编辑。该属性只有两个值on和off，默认值为off。一旦设为on，用户就可以编辑整个文档的内容。
  // 2.7、document.currentScript：document.currentScript属性只用在<script>元素的内嵌脚本或加载的外部脚本之中，返回当前脚本所在的那个 DOM 节点，即<script>元素的 DOM 节点。
  // 2.8、document.implementation：document.implementation属性返回一个DOMImplementation对象。该对象有三个方法，主要用于创建独立于当前文档的新的 Document 对象。
  //   DOMImplementation.createDocument()：创建一个 XML 文档。
  //   DOMImplementation.createHTMLDocument()：创建一个 HTML 文档。
  //   DOMImplementation.createDocumentType()：创建一个 DocumentType 对象。
// 3、方法
//   3.1、document.open()，document.close()：document.open方法清除当前文档所有内容，使得文档处于可写状态，供document.write方法写入内容。
//   3.2、document.write()，document.writeln()：document.write方法用于向当前文档写入内容。在网页的首次渲染阶段，只要页面没有关闭写入（即没有执行document.close()），document.write写入的内容就会追加在已有内容的后面。
//   3.3、document.querySelector()，document.querySelectorAll()：document.querySelector方法接受一个 CSS 选择器作为参数，返回匹配该选择器的元素节点。如果有多个节点满足匹配条件，则返回第一个匹配的节点。如果没有发现匹配的节点，则返回null。
//   3.4、document.getElementsByTagName()：document.getElementsByTagName()方法搜索 HTML 标签名，返回符合条件的元素。它的返回值是一个类似数组对象（HTMLCollection实例），可以实时反映 HTML 文档的变化。如果没有任何匹配的元素，就返回一个空集。
//   3.5、document.getElementsByClassName()：document.getElementsByClassName()方法返回一个类似数组的对象（HTMLCollection实例），包括了所有class名字符合指定条件的元素，元素的变化实时反映在返回结果中。
//   3.6、document.getElementsByName()：document.getElementsByName()方法用于选择拥有name属性的 HTML 元素（比如<form>、<radio>、<img>、<frame>、<embed>和<object>等），返回一个类似数组的的对象（NodeList实例），因为name属性相同的元素可能不止一个。
//   3.7、document.getElementById()：document.getElementById()方法返回匹配指定id属性的元素节点。如果没有发现匹配的节点，则返回null。
//   3.8、document.elementFromPoint()，document.elementsFromPoint()：document.elementFromPoint()方法返回位于页面指定位置最上层的元素节点。
//   3.9、document.createElement()：document.createElement方法用来生成元素节点，并返回该节点。
//   3.10、document.createTextNode()：document.createTextNode方法用来生成文本节点（Text实例），并返回该节点。它的参数是文本节点的内容。
//   3.11、document.createAttribute()：document.createAttribute方法生成一个新的属性节点（Attr实例），并返回它。
//   3.12、document.createComment()：document.createComment方法生成一个新的注释节点，并返回该节点。
//   3.13、document.createDocumentFragment()：document.createDocumentFragment方法生成一个空的文档片段对象（DocumentFragment实例）。
//   3.14、document.createEvent()：document.createEvent方法生成一个事件对象（Event实例），该对象可以被element.dispatchEvent方法使用，触发指定事件。
//   3.15、document.addEventListener()，document.removeEventListener()，document.dispatchEvent()：这三个方法用于处理document节点的事件。它们都继承自EventTarget接口，详细介绍参见《EventTarget 接口》一章。
//   3.16、document.hasFocus()：document.hasFocus方法返回一个布尔值，表示当前文档之中是否有元素被激活或获得焦点。
//   3.17、document.adoptNode()，document.importNode()：document.adoptNode方法将某个节点及其子节点，从原来所在的文档或DocumentFragment里面移除，归属当前document对象，返回插入后的新节点。插入的节点对象的ownerDocument属性，会变成当前的document对象，而parentNode属性是null。
//   3.18、document.createNodeIterator()：document.createNodeIterator方法返回一个子节点遍历器。
//   var nodeIterator = document.createNodeIterator(
//     document.body,
//     NodeFilter.SHOW_ELEMENT
//   );
//   上面代码返回<body>元素子节点的遍历器。
//   document.createNodeIterator方法第一个参数为所要遍历的根节点，第二个参数为所要遍历的节点类型，这里指定为元素节点（NodeFilter.SHOW_ELEMENT）。几种主要的节点类型写法如下。
//     所有节点：NodeFilter.SHOW_ALL
//     元素节点：NodeFilter.SHOW_ELEMENT
//     文本节点：NodeFilter.SHOW_TEXT
//     评论节点：NodeFilter.SHOW_COMMENT
//   document.createNodeIterator方法返回一个“遍历器”对象（NodeFilter实例）。该实例的nextNode()方法和previousNode()方法，可以用来遍历所有子节点。
  // 3.19、document.createTreeWalker()：document.createTreeWalker方法返回一个 DOM 的子树遍历器。它与document.createNodeIterator方法基本是类似的，区别在于它返回的是TreeWalker实例，后者返回的是NodeIterator实例。另外，它的第一个节点不是根节点。
  // 3.20、document.execCommand()，document.queryCommandSupported()，document.queryCommandEnabled()：NodeList实例是一个类似数组的对象，它的成员是节点对象。通过以下方法可以得到NodeList实例。
  // （1）、document.execCommand()：如果document.designMode属性设为on，那么整个文档用户可编辑；如果元素的contenteditable属性设为true，那么该元素可编辑。这两种情况下，可以使用document.execCommand()方法，改变内容的样式，比如document.execCommand('bold')会使得字体加粗。
  //   document.execCommand(command, showDefaultUI, input)
  //   该方法接受三个参数。
  //   command：字符串，表示所要实施的样式。
  //   showDefaultUI：布尔值，表示是否要使用默认的用户界面，建议总是设为false。
  //   input：字符串，表示该样式的辅助内容，比如生成超级链接时，这个参数就是所要链接的网址。如果第二个参数设为true，那么浏览器会弹出提示框，要求用户在提示框输入该参数。但是，不是所有浏览器都支持这样做，为了兼容性，还是需要自己部署获取这个参数的方式。
  // （2）、document.queryCommandSupported()：document.queryCommandSupported()方法返回一个布尔值，表示浏览器是否支持document.execCommand()的某个命令。
  // （3）、document.queryCommandEnabled()：document.queryCommandEnabled()方法返回一个布尔值，表示当前是否可用document.execCommand()的某个命令。比如，bold（加粗）命令只有存在文本选中时才可用，如果没有选中文本，就不可用。
  // 3.21、document.getSelection()：这个方法指向window.getSelection()，参见window对象一节的介绍

// 六、Element 节点
// 1、简介：Element节点对象对应网页的 HTML 元素。每一个 HTML 元素，在 DOM 树上都会转化成一个Element节点对象（以下简称元素节点）。
// 2、实例属性
//   2.1、元素特性的相关属性：
//   （1）、Element.id：Element.id属性返回指定元素的id属性，该属性可读写。
//   （2）、Element.tagName：Element.tagName属性返回指定元素的大写标签名，与nodeName属性的值相等。
//   （3）、Element.dir：Element.dir属性用于读写当前元素的文字方向，可能是从左到右（"ltr"），也可能是从右到左（"rtl"）。
//   （4）、Element.accessKey：Element.accessKey属性用于读写分配给当前元素的快捷键。
//   （5）、Element.draggable：Element.draggable属性返回一个布尔值，表示当前元素是否可拖动。该属性可读写。
//   （6）、Element.lang：Element.lang属性返回当前元素的语言设置。该属性可读写。
//   （7）、Element.tabIndex：Element.tabIndex属性返回一个整数，表示当前元素在 Tab 键遍历时的顺序。该属性可读写。
//   （8）、Element.title：Element.title属性用来读写当前元素的 HTML 属性title。该属性通常用来指定，鼠标悬浮时弹出的文字提示框。
//   2.2、元素状态的相关属性
//   （1）、Element.hidden：Element.hidden属性返回一个布尔值，表示当前元素的hidden属性，用来控制当前元素是否可见。该属性可读写。
//   （2）、Element.contentEditable，Element.isContentEditable：HTML 元素可以设置contentEditable属性，使得元素的内容可以编辑。
//     Element.contentEditable属性返回一个字符串，表示是否设置了contenteditable属性，有三种可能的值。该属性可写。
//     "true"：元素内容可编辑
//     "false"：元素内容不可编辑
//     "inherit"：元素是否可编辑，继承了父元素的设置
//     Element.isContentEditable属性返回一个布尔值，同样表示是否设置了contenteditable属性。该属性只读。
//   2.3、Element.attributes：Element.attributes属性返回一个类似数组的对象，成员是当前元素节点的所有属性节点，详见《属性的操作》一章。
//   2.4、Element.className，Element.classList：
//     className属性用来读写当前元素节点的class属性。它的值是一个字符串，每个class之间用空格分割。
//     classList属性返回一个类似数组的对象，当前元素节点的每个class就是这个对象的一个成员。
//     classList对象有下列方法。
//       add()：增加一个 class。
//       remove()：移除一个 class。
//       contains()：检查当前元素是否包含某个 class。
//       toggle()：将某个 class 移入或移出当前元素。
//       item()：返回指定索引位置的 class。
//       toString()：将 class 的列表转为字符串。
//   2.5、Element.dataset：网页元素可以自定义data-属性，用来添加数据。
//     HTML 代码中，data-属性的属性名，只能包含英文字母、数字、连词线（-）、点（.）、冒号（:）和下划线（_）。它们转成 JavaScript 对应的dataset属性名，规则如下。
//     开头的data-会省略。
//     如果连词线后面跟了一个英文字母，那么连词线会取消，该字母变成大写。
//     其他字符不变。
//   2.6、Element.innerHTML：Element.innerHTML属性返回一个字符串，等同于该元素包含的所有 HTML 代码。该属性可读写，常用来设置某个节点的内容。它能改写所有元素节点的内容，包括<HTML>和<body>元素。
//   2.7、Element.outerHTML：Element.outerHTML属性返回一个字符串，表示当前元素节点的所有 HTML 代码，包括该元素本身和所有子元素。
//   2.8、Element.clientHeight，Element.clientWidth：
//     Element.clientHeight属性返回一个整数值，表示元素节点的 CSS 高度（单位像素），只对块级元素生效，对于行内元素返回0。如果块级元素没有设置 CSS 高度，则返回实际高度。
//     除了元素本身的高度，它还包括padding部分，但是不包括border、margin。如果有水平滚动条，还要减去水平滚动条的高度。注意，这个值始终是整数，如果是小数会被四舍五入。
//     Element.clientWidth属性返回元素节点的 CSS 宽度，同样只对块级元素有效，也是只包括元素本身的宽度和padding，如果有垂直滚动条，还要减去垂直滚动条的宽度。
//     document.documentElement的clientHeight属性，返回当前视口的高度（即浏览器窗口的高度），等同于window.innerHeight属性减去水平滚动条的高度（如果有的话）。
//     document.body的高度则是网页的实际高度。一般来说，document.body.clientHeight大于document.documentElement.clientHeight。
//   2.9、Element.clientLeft，Element.clientTop：
//     Element.clientLeft属性等于元素节点左边框（left border）的宽度（单位像素），不包括左侧的padding和margin。如果没有设置左边框，或者是行内元素（display: inline），该属性返回0。该属性总是返回整数值，如果是小数，会四舍五入。
//     Element.clientTop属性等于网页元素顶部边框的宽度（单位像素），其他特点都与clientLeft相同。
//   2.10、Element.scrollHeight，Element.scrollWidth：
//     Element.scrollHeight属性返回一个整数值（小数会四舍五入），表示当前元素的总高度（单位像素），包括溢出容器、当前不可见的部分。它包括padding，但是不包括border、margin以及水平滚动条的高度（如果有水平滚动条的话），还包括伪元素（::before或::after）的高度。
//     Element.scrollWidth属性表示当前元素的总宽度（单位像素），其他地方都与scrollHeight属性类似。这两个属性只读。
//   2.11、Element.scrollLeft，Element.scrollTop：Element.scrollLeft属性表示当前元素的水平滚动条向右侧滚动的像素数量，Element.scrollTop属性表示当前元素的垂直滚动条向下滚动的像素数量。对于那些没有滚动条的网页元素，这两个属性总是等于0。
//   2.12、Element.offsetParent：Element.offsetParent属性返回最靠近当前元素的、并且 CSS 的position属性不等于static的上层元素。
//   2.13、Element.offsetHeight，Element.offsetWidth：
//     Element.offsetHeight属性返回一个整数，表示元素的 CSS 垂直高度（单位像素），包括元素本身的高度、padding 和 border，以及水平滚动条的高度（如果存在滚动条）。
//     Element.offsetWidth属性表示元素的 CSS 水平宽度（单位像素），其他都与Element.offsetHeight一致。
//   2.14、Element.offsetLeft，Element.offsetTop：
//     Element.offsetLeft返回当前元素左上角相对于Element.offsetParent节点的水平位移，Element.offsetTop返回垂直位移，单位为像素。通常，这两个值是指相对于父节点的位移。
//   2.15、Element.style：每个元素节点都有style用来读写该元素的行内样式信息，具体介绍参见《CSS 操作》一章。
//   2.16、Element.children，Element.childElementCount：Element.children属性返回一个类似数组的对象（HTMLCollection实例），包括当前元素节点的所有子元素。如果当前元素没有子元素，则返回的对象包含零个成员。与Node.childNodes属性的区别是，它只包括元素类型的子节点，不包括其他类型的子节点。
//     Element.childElementCount属性返回当前元素节点包含的子元素节点的个数，与Element.children.length的值相同。
//   2.17、Element.firstElementChild，Element.lastElementChild：Element.firstElementChild属性返回当前元素的第一个元素子节点，Element.lastElementChild返回最后一个元素子节点。如果没有元素子节点，这两个属性返回null。
//   2.18、Element.nextElementSibling，Element.previousElementSibling：
//     Element.nextElementSibling属性返回当前元素节点的后一个同级元素节点，如果没有则返回null。
//     Element.previousElementSibling属性返回当前元素节点的前一个同级元素节点，如果没有则返回null。
// 3、实例方法
//   3.1、属性相关方法：元素节点提供六个方法，用来操作属性。
//     getAttribute()：读取某个属性的值
//     getAttributeNames()：返回当前元素的所有属性名
//     setAttribute()：写入属性值
//     hasAttribute()：某个属性是否存在
//     hasAttributes()：当前元素是否有属性
//     removeAttribute()：删除属性
//   3.2、Element.querySelector()：Element.querySelector方法接受 CSS 选择器作为参数，返回父元素的第一个匹配的子元素。如果没有找到匹配的子元素，就返回null。
//   3.3、Element.querySelectorAll()：Element.querySelectorAll方法接受 CSS 选择器作为参数，返回一个NodeList实例，包含所有匹配的子元素。
//   3.4、Element.getElementsByClassName()：Element.getElementsByClassName方法返回一个HTMLCollection实例，成员是当前元素节点的所有具有指定 class 的子元素节点。该方法与document.getElementsByClassName方法的用法类似，只是搜索范围不是整个文档，而是当前元素节点。
//   3.5、Element.getElementsByTagName()：Element.getElementsByTagName()方法返回一个HTMLCollection实例，成员是当前节点的所有匹配指定标签名的子元素节点。该方法与document.getElementsByClassName()方法的用法类似，只是搜索范围不是整个文档，而是当前元素节点。
//   3.6、Element.closest()：Element.closest方法接受一个 CSS 选择器作为参数，返回匹配该选择器的、最接近当前节点的一个祖先节点（包括当前节点本身）。如果没有任何节点匹配 CSS 选择器，则返回null。
//   3.7、Element.matches()：Element.matches方法返回一个布尔值，表示当前元素是否匹配给定的 CSS 选择器。
//   3.8、事件相关方法：以下三个方法与Element节点的事件相关。这些方法都继承自EventTarget接口，详见相关章节。
//     Element.addEventListener()：添加事件的回调函数
//     Element.removeEventListener()：移除事件监听函数
//     Element.dispatchEvent()：触发事件
//   3.9、Element.scrollIntoView()：Element.scrollIntoView方法滚动当前元素，进入浏览器的可见区域，类似于设置window.location.hash的效果。
//   3.10、Element.getBoundingClientRect()：Element.getBoundingClientRect方法返回一个对象，提供当前元素节点的大小、位置等信息，基本上就是 CSS 盒状模型的所有信息。
//     var rect = obj.getBoundingClientRect();
//     上面代码中，getBoundingClientRect方法返回的rect对象，具有以下属性（全部为只读）。
//       x：元素左上角相对于视口的横坐标
//       y：元素左上角相对于视口的纵坐标
//       height：元素高度
//       width：元素宽度
//       left：元素左上角相对于视口的横坐标，与x属性相等
//       right：元素右边界相对于视口的横坐标（等于x + width）
//       top：元素顶部相对于视口的纵坐标，与y属性相等
//       bottom：元素底部相对于视口的纵坐标（等于y + height）
//   3.11、Element.getClientRects()：Element.getClientRects方法返回一个类似数组的对象，里面是当前元素在页面上形成的所有矩形（所以方法名中的Rect用的是复数）。每个矩形都有bottom、height、left、right、top和width六个属性，表示它们相对于视口的四个坐标，以及本身的高度和宽度。
//   3.12、Element.insertAdjacentElement()：Element.insertAdjacentElement方法在相对于当前元素的指定位置，插入一个新的节点。该方法返回被插入的节点，如果插入失败，返回null。
//   3.13、Element.insertAdjacentHTML()，Element.insertAdjacentText()：
//     Element.insertAdjacentHTML方法用于将一个 HTML 字符串，解析生成 DOM 结构，插入相对于当前节点的指定位置。
//       该方法接受两个参数，第一个是一个表示指定位置的字符串，第二个是待解析的 HTML 字符串。第一个参数只能设置下面四个值之一。
//       beforebegin：当前元素之前
//       afterbegin：当前元素内部的第一个子节点前面
//       beforeend：当前元素内部的最后一个子节点后面
//       afterend：当前元素之后
//     Element.insertAdjacentText方法在相对于当前节点的指定位置，插入一个文本节点，用法与Element.insertAdjacentHTML方法完全一致。
//   3.14、Element.remove()：Element.remove方法继承自 ChildNode 接口，用于将当前元素节点从它的父节点移除。
//   3.15、Element.focus()，Element.blur()：Element.focus方法用于将当前页面的焦点，转移到指定元素上。
//   3.16、Element.click()：Element.click方法用于在当前元素上模拟一次鼠标点击，相当于触发了click事件。

// 七、属性的操作
// HTML 元素包括标签名和若干个键值对，这个键值对就称为“属性”（attribute）。
// 1、Element.attributes 属性：
//   元素对象有一个attributes属性，返回一个类似数组的动态对象，成员是该元素标签的所有属性节点对象，属性的实时变化都会反映在这个节点对象上。其他类型的节点对象，虽然也有attributes属性，但返回的都是null，因此可以把这个属性视为元素对象独有的。
// 2、元素的标准属性：HTML 元素的标准属性（即在标准中定义的属性），会自动成为元素节点对象的属性。
// 3、属性操作的标准方法
//   3.1、概述
//   元素节点提供六个方法，用来操作属性。
//     getAttribute()
//     getAttributeNames()
//     setAttribute()
//     hasAttribute()
//     hasAttributes()
//     removeAttribute()
//   这有几点注意。
//   （1）适用性：这六个方法对所有属性（包括用户自定义的属性）都适用。
//   （2）返回值：getAttribute()只返回字符串，不会返回其他类型的值。
//   （3）属性名：这些方法只接受属性的标准名称，不用改写保留字，比如for和class都可以直接使用。另外，这些方法对于属性名是大小写不敏感的。
//   3.2、Element.getAttribute()：Element.getAttribute方法返回当前元素节点的指定属性。如果指定属性不存在，则返回null。
//   3.3、Element.getAttributeNames()：
//     Element.getAttributeNames()返回一个数组，成员是当前元素的所有属性的名字。如果当前元素没有任何属性，则返回一个空数组。使用Element.attributes属性，也可以拿到同样的结果，唯一的区别是它返回的是类似数组的对象。
//   3.4、Element.setAttribute()：Element.setAttribute方法用于为当前元素节点新增属性。如果同名属性已存在，则相当于编辑已存在的属性。该方法没有返回值。
//   3.5、Element.hasAttribute()：Element.hasAttribute方法返回一个布尔值，表示当前元素节点是否包含指定属性。
//   3.6、Element.hasAttributes()：Element.hasAttributes方法返回一个布尔值，表示当前元素是否有属性，如果没有任何属性，就返回false，否则返回true。
//   3.7、Element.removeAttribute()：Element.removeAttribute方法移除指定属性。该方法没有返回值。
// 4、dataset 属性：有时，需要在HTML元素上附加数据，供 JavaScript 脚本使用。一种解决方法是自定义属性。解决方法是，使用标准提供的data-*属性。
//   然后，使用元素节点对象的dataset属性，它指向一个对象，可以用来操作 HTML 元素标签的data-*属性。
//   除了dataset属性，也可以用getAttribute('data-foo')、removeAttribute('data-foo')、setAttribute('data-foo')、hasAttribute('data-foo')等方法操作data-*属性。

// 八、Text 节点和 DocumentFragment 节点
// 1、Text 节点的概念：
//   文本节点（Text）代表元素节点（Element）和属性节点（Attribute）的文本内容。如果一个节点只包含一段文本，那么它就有一个文本子节点，代表该节点的文本内容。
// 2、Text 节点的属性
//   2.1、data：data属性等同于nodeValue属性，用来设置或读取文本节点的内容。
//   2.2、wholeText：wholeText属性将当前文本节点与毗邻的文本节点，作为一个整体返回。大多数情况下，wholeText属性的返回值，与data属性和textContent属性相同。但是，某些特殊情况会有差异。
//   2.3、length：length属性返回当前文本节点的文本长度。
//   2.4、nextElementSibling，previousElementSibling：nextElementSibling属性返回紧跟在当前文本节点后面的那个同级元素节点。如果取不到元素节点，则返回null。
// 3、Text 节点的方法 
//   3.1、appendData()，deleteData()，insertData()，replaceData()，subStringData()
//     以下5个方法都是编辑Text节点文本内容的方法。
//     appendData()：在Text节点尾部追加字符串。
//     deleteData()：删除Text节点内部的子字符串，第一个参数为子字符串开始位置，第二个参数为子字符串长度。
//     insertData()：在Text节点插入字符串，第一个参数为插入位置，第二个参数为插入的子字符串。
//     replaceData()：用于替换文本，第一个参数为替换开始位置，第二个参数为需要被替换掉的长度，第三个参数为新加入的字符串。
//     subStringData()：用于获取子字符串，第一个参数为子字符串在Text节点中的开始位置，第二个参数为子字符串长度。
//   3.2、remove()：remove方法用于移除当前Text节点。
//   3.3、splitText()：splitText方法将Text节点一分为二，变成两个毗邻的Text节点。它的参数就是分割位置（从零开始），分割到该位置的字符前结束。如果分割位置不存在，将报错。
// 4、DocumentFragment 节点
//   DocumentFragment节点代表一个文档的片段，本身就是一个完整的 DOM 树形结构。它没有父节点，parentNode返回null，但是可以插入任意数量的子节点。它不属于当前文档，操作DocumentFragment节点，要比直接操作 DOM 树快得多。
//   DocumentFragment节点对象没有自己的属性和方法，全部继承自Node节点和ParentNode接口。也就是说，DocumentFragment节点比Node节点多出以下四个属性。
//     children：返回一个动态的HTMLCollection集合对象，包括当前DocumentFragment对象的所有子元素节点。
//     firstElementChild：返回当前DocumentFragment对象的第一个子元素节点，如果没有则返回null。
//     lastElementChild：返回当前DocumentFragment对象的最后一个子元素节点，如果没有则返回null。
//     childElementCount：返回当前DocumentFragment对象的所有子元素数量。

// 九、CSS 操作
//   本章介绍如何通过 JavaScript 操作 CSS
// 1、HTML 元素的 style 属性：操作 CSS 样式最简单的方法，就是使用网页元素节点的getAttribute()方法、setAttribute()方法和removeAttribute()方法，直接读写或删除网页元素的style属性。
// 2、CSSStyleDeclaration 接口
//   2.1、简介：CSSStyleDeclaration 接口用来操作元素的样式。三个地方部署了这个接口。
//     元素节点的style属性（Element.style）
//     CSSStyle实例的style属性
//     window.getComputedStyle()的返回值
//   2.2、CSSStyleDeclaration 实例属性
//   （1）、CSSStyleDeclaration.cssText：CSSStyleDeclaration.cssText属性用来读写当前规则的所有样式声明文本。注意，cssText的属性值不用改写 CSS 属性名。
//   （2）、CSSStyleDeclaration.length：CSSStyleDeclaration.length属性返回一个整数值，表示当前规则包含多少条样式声明。
//   （3）、CSSStyleDeclaration.parentRule：CSSStyleDeclaration.parentRule属性返回当前规则所属的那个样式块（CSSRule 实例）。如果不存在所属的样式块，该属性返回null。
//   2.3、CSSStyleDeclaration 实例方法
//   （1）、CSSStyleDeclaration.getPropertyPriority()：CSSStyleDeclaration.getPropertyPriority方法接受 CSS 样式的属性名作为参数，返回一个字符串，表示有没有设置important优先级。如果有就返回important，否则返回空字符串。
//   （2）、CSSStyleDeclaration.getPropertyValue()：CSSStyleDeclaration.getPropertyValue方法接受 CSS 样式属性名作为参数，返回一个字符串，表示该属性的属性值。
//   （3）、CSSStyleDeclaration.item()：CSSStyleDeclaration.item方法接受一个整数值作为参数，返回该位置的 CSS 属性名。
//   （4）、CSSStyleDeclaration.removeProperty()：CSSStyleDeclaration.removeProperty方法接受一个属性名作为参数，在 CSS 规则里面移除这个属性，返回这个属性原来的值。
//   （5）、CSSStyleDeclaration.setProperty()：CSSStyleDeclaration.setProperty方法用来设置新的 CSS 属性。该方法没有返回值。
//     该方法可以接受三个参数。
//       第一个参数：属性名，该参数是必需的。
//       第二个参数：属性值，该参数可选。如果省略，则参数值默认为空字符串。
//       第三个参数：优先级，该参数可选。如果设置，唯一的合法值是important，表示 CSS 规则里面的!important。
// 3、CSS 模块的侦测
//   CSS 的规格发展太快，新的模块层出不穷。不同浏览器的不同版本，对 CSS 模块的支持情况都不一样。有时候，需要知道当前浏览器是否支持某个模块，这就叫做“CSS模块的侦测”。
//   一个比较普遍适用的方法是，判断元素的style对象的某个属性值是否为字符串。
//   typeof element.style.animationName === 'string';
//   typeof element.style.transform === 'string';
//   如果该 CSS 属性确实存在，会返回一个字符串。即使该属性实际上并未设置，也会返回一个空字符串。如果该属性不存在，则会返回undefined。
//   document.body.style['maxWidth'] // ""
//   document.body.style['maximumWidth'] // undefined
//   上面代码说明，这个浏览器支持max-width属性，但是不支持maximum-width属性。
// 4、CSS 对象
//   浏览器原生提供 CSS 对象，为 JavaScript 操作 CSS 提供一些工具方法。
//   这个对象目前有两个静态方法。
//   4.1、CSS.escape()：CSS.escape方法用于转义 CSS 选择器里面的特殊字符。
//   4.2、CSS.supports()：CSS.supports方法返回一个布尔值，表示当前环境是否支持某一句 CSS 规则。
//     它的参数有两种写法，一种是第一个参数是属性名，第二个参数是属性值；另一种是整个参数就是一行完整的 CSS 语句。
// 5、window.getComputedStyle()：行内样式（inline style）具有最高的优先级，改变行内样式，通常会立即反映出来。但是，网页元素最终的样式是综合各种规则计算出来的。因此，如果想得到元素实际的样式，只读取行内样式是不够的，需要得到浏览器最终计算出来的样式规则。
//   window.getComputedStyle方法，就用来返回浏览器计算后得到的最终规则。它接受一个节点对象作为参数，返回一个 CSSStyleDeclaration 实例，包含了指定节点的最终样式信息。所谓“最终样式信息”，指的是各种 CSS 规则叠加后的结果。
//   getComputedStyle方法还可以接受第二个参数，表示当前元素的伪元素（比如:before、:after、:first-line、:first-letter等）。
//   有几点需要注意。
//     CSSStyleDeclaration 实例返回的 CSS 值都是绝对单位。比如，长度都是像素单位（返回值包括px后缀），颜色是rgb(#, #, #)或rgba(#, #, #, #)格式。
//     CSS 规则的简写形式无效。比如，想读取margin属性的值，不能直接读，只能读marginLeft、marginTop等属性；再比如，font属性也是不能直接读的，只能读font-size等单个属性。
//     如果读取 CSS 原始的属性名，要用方括号运算符，比如styleObj['z-index']；如果读取骆驼拼写法的 CSS 属性名，可以直接读取styleObj.zIndex。
//     该方法返回的 CSSStyleDeclaration 实例的cssText属性无效，返回undefined。
// 6、CSS 伪元素：
//   CSS 伪元素是通过 CSS 向 DOM 添加的元素，主要是通过:before和:after选择器生成，然后用content属性指定伪元素的内容。
//   节点元素的style对象无法读写伪元素的样式，这时就要用到window.getComputedStyle()。JavaScript 获取伪元素，可以使用下面的方法。
//   var test = document.querySelector('#test');
//   var result = window.getComputedStyle(test, ':before').content;
//   var color = window.getComputedStyle(test, ':before').color;
//   此外，也可以使用 CSSStyleDeclaration 实例的getPropertyValue方法，获取伪元素的属性。
//   var result = window.getComputedStyle(test, ':before').getPropertyValue('content');
//   var color = window.getComputedStyle(test, ':before').getPropertyValue('color');
// 7、StyleSheet 接口
//   7.1、概述：StyleSheet接口代表网页的一张样式表，包括<link>元素加载的样式表和<style>元素内嵌的样式表。
//     document对象的styleSheets属性，可以返回当前页面的所有StyleSheet实例（即所有样式表）。它是一个类似数组的对象。
//   7.2、实例属性：StyleSheet实例有以下属性。
//   （1）、StyleSheet.disabled：
//     StyleSheet.disabled返回一个布尔值，表示该样式表是否处于禁用状态。手动设置disabled属性为true，等同于在<link>元素里面，将这张样式表设为alternate stylesheet，即该样式表将不会生效。
//     注意，disabled属性只能在 JavaScript 脚本中设置，不能在 HTML 语句中设置。
//   （2）、Stylesheet.href：Stylesheet.href返回样式表的网址。对于内嵌样式表，该属性返回null。该属性只读。
//   （3）、StyleSheet.media：StyleSheet.media属性返回一个类似数组的对象（MediaList实例），成员是表示适用媒介的字符串。表示当前样式表是用于屏幕（screen），还是用于打印（print）或手持设备（handheld），或各种媒介都适用（all）。该属性只读，默认值是screen。
//   （4）、StyleSheet.title：StyleSheet.title属性返回样式表的title属性。
//   （5）、StyleSheet.type：StyleSheet.type属性返回样式表的type属性，通常是text/css。
//   （6）、StyleSheet.parentStyleSheet：CSS 的@import命令允许在样式表中加载其他样式表。StyleSheet.parentStyleSheet属性返回包含了当前样式表的那张样式表。如果当前样式表是顶层样式表，则该属性返回null。
//   （7）、StyleSheet.ownerNode：StyleSheet.ownerNode属性返回StyleSheet对象所在的 DOM 节点，通常是<link>或<style>。对于那些由其他样式表引用的样式表，该属性为null。
//   （8）、CSSStyleSheet.cssRules：CSSStyleSheet.cssRules属性指向一个类似数组的对象（CSSRuleList实例），里面每一个成员就是当前样式表的一条 CSS 规则。使用该规则的cssText属性，可以得到 CSS 规则对应的字符串。
//   （9）、CSSStyleSheet.ownerRule：有些样式表是通过@import规则输入的，它的ownerRule属性会返回一个CSSRule实例，代表那行@import规则。如果当前样式表不是通过@import引入的，ownerRule属性返回null。
//   7.3、实例方法：
//   （1）CSSStyleSheet.insertRule()：CSSStyleSheet.insertRule方法用于在当前样式表的插入一个新的 CSS 规则。
//   （2）CSSStyleSheet.deleteRule()：CSSStyleSheet.deleteRule方法用来在样式表里面移除一条规则，它的参数是该条规则在cssRules对象中的位置。该方法没有返回值。
// 8、实例：添加样式表：网页添加样式表有两种方式。一种是添加一张内置样式表，即在文档中添加一个<style>节点
//   // 写法一
//   var style = document.createElement('style');
//   style.setAttribute('media', 'screen');
//   style.innerHTML = 'body{color:red}';
//   document.head.appendChild(style);

//   // 写法二
//   var style = (function () {
//     var style = document.createElement('style');
//     document.head.appendChild(style);
//     return style;
//   })();
  // style.sheet.insertRule('.foo{color:red;}', 0);
  // 另一种是添加外部样式表，即在文档中添加一个<link>节点，然后将href属性指向外部样式表的 URL。
  // var linkElm = document.createElement('link');
  // linkElm.setAttribute('rel', 'stylesheet');
  // linkElm.setAttribute('type', 'text/css');
  // linkElm.setAttribute('href', 'reset-min.css');
  // document.head.appendChild(linkElm);
// 9、CSSRuleList 接口：CSSRuleList 接口是一个类似数组的对象，表示一组 CSS 规则，成员都是 CSSRule 实例。
//   获取 CSSRuleList 实例，一般是通过StyleSheet.cssRules属性。
//   CSSRuleList 实例里面，每一条规则（CSSRule 实例）可以通过rules.item(index)或者rules[index]拿到。CSS 规则的条数通过rules.length拿到。还是用上面的例子。
// 10、CSSRule 接口 
//   10.1、概述：一条 CSS 规则包括两个部分：CSS 选择器和样式声明。
//     JavaScript 通过 CSSRule 接口操作 CSS 规则。一般通过 CSSRuleList 接口（StyleSheet.cssRules）获取 CSSRule 实例。
//   10.2、CSSRule 实例的属性：
//   （1）、CSSRule.cssText：CSSRule.cssText属性返回当前规则的文本
//   （2）、CSSRule.parentStyleSheet：CSSRule.parentStyleSheet属性返回当前规则所在的样式表对象（StyleSheet 实例）
//   （3）CSSRule.parentRule：CSSRule.parentRule属性返回包含当前规则的父规则，如果不存在父规则（即当前规则是顶层规则），则返回null。父规则最常见的情况是，当前规则包含在@media规则代码块之中。
//   （4）CSSRule.type：CSSRule.type属性返回一个整数值，表示当前规则的类型。
//     最常见的类型有以下几种。
//     1：普通样式规则（CSSStyleRule 实例）
//     3：@import规则
//     4：@media规则（CSSMediaRule 实例）
//     5：@font-face规则
//   10.3、CSSStyleRule 接口：如果一条 CSS 规则是普通的样式规则（不含特殊的 CSS 命令），那么除了 CSSRule 接口，它还部署了 CSSStyleRule 接口。
//     CSSStyleRule 接口有以下两个属性。
//   （1）CSSStyleRule.selectorText：CSSStyleRule.selectorText属性返回当前规则的选择器。
//   （2）CSSStyleRule.style：CSSStyleRule.style属性返回一个对象（CSSStyleDeclaration 实例），代表当前规则的样式声明，也就是选择器后面的大括号里面的部分。
//   10.4、CSSMediaRule 接口
//     如果一条 CSS 规则是@media代码块，那么它除了 CSSRule 接口，还部署了 CSSMediaRule 接口。
//     该接口主要提供media属性和conditionText属性。前者返回代表@media规则的一个对象（MediaList 实例），后者返回@media规则的生效条件。
// 11、window.matchMedia()
//   11.1、基本用法：window.matchMedia方法用来将 CSS 的MediaQuery条件语句，转换成一个 MediaQueryList 实例。
//   11.2、MediaQueryList 接口的实例属性：MediaQueryList 实例有三个属性
//   （1）、MediaQueryList.media：MediaQueryList.media属性返回一个字符串，表示对应的 MediaQuery 条件语句。
//   （2）、MediaQueryList.matches：MediaQueryList.matches属性返回一个布尔值，表示当前页面是否符合指定的 MediaQuery 条件语句。
//   （3）MediaQueryList.onchange：如果 MediaQuery 条件语句的适配环境发生变化，会触发change事件。MediaQueryList.onchange属性用来指定change事件的监听函数。该函数的参数是change事件对象（MediaQueryListEvent 实例），该对象与 MediaQueryList 实例类似，也有media和matches属性。
//   11.3、MediaQueryList 接口的实例方法：MediaQueryList 实例有两个方法MediaQueryList.addListener()和MediaQueryList.removeListener()，用来为change事件添加或撤销监听函数。
//     注意，MediaQueryList.removeListener()方法不能撤销MediaQueryList.onchange属性指定的监听函数。

// 十、Mutation Observer API
// 1、概述：Mutation Observer API 用来监视 DOM 变动。DOM 的任何变动，比如节点的增减、属性的变动、文本内容的变动，这个 API 都可以得到通知。
//   概念上，它很接近事件，可以理解为 DOM 发生变动就会触发 Mutation Observer 事件。但是，它与事件有一个本质不同：事件是同步触发，也就是说，DOM 的变动立刻会触发相应的事件；Mutation Observer 则是异步触发，DOM 的变动并不会马上触发，而是要等到当前所有 DOM 操作都结束才触发。
//   Mutation Observer 有以下特点。
//     它等待所有脚本任务完成后，才会运行（即异步触发方式）。
//     它把 DOM 变动记录封装成一个数组进行处理，而不是一条条个别处理 DOM 变动。
//     它既可以观察 DOM 的所有类型变动，也可以指定只观察某一类变动。
// 2、MutationObserver 构造函数：使用时，首先使用MutationObserver构造函数，新建一个观察器实例，同时指定这个实例的回调函数。
// 3、MutationObserver 的实例方法 
  // 3.1、observe()：observe()方法用来启动监听，它接受两个参数。
  //   第一个参数：所要观察的 DOM 节点
  //   第二个参数：一个配置对象，指定所要观察的特定变动。
  //   观察器所能观察的 DOM 变动类型，有以下几种。
  //   childList：子节点的变动（指新增，删除或者更改）。
  //   attributes：属性的变动。
  //   characterData：节点内容或节点文本的变动。
  //   除了变动类型，options对象还可以设定以下属性：
  //   subtree：布尔值，表示是否将该观察器应用于该节点的所有后代节点。
  //   attributeOldValue：布尔值，表示观察attributes变动时，是否需要记录变动前的属性值。
  //   characterDataOldValue：布尔值，表示观察characterData变动时，是否需要记录变动前的值。
  //   attributeFilter：数组，表示需要观察的特定属性（比如['class','src']）。
  // 3.2、disconnect()，takeRecords（）：
  //   disconnect()方法用来停止观察。调用该方法后，DOM 再发生变动，也不会触发观察器。
  //   takeRecords()方法用来清除变动记录，即不再处理未处理的变动。该方法返回变动记录的数组。
// 4、MutationRecord 对象
//   DOM 每次发生变化，就会生成一条变动记录（MutationRecord 实例）。该实例包含了与变动相关的所有信息。Mutation Observer 处理的就是一个个MutationRecord实例所组成的数组。
//   MutationRecord对象包含了DOM的相关信息，有如下属性：
//     type：观察的变动类型（attributes、characterData或者childList）。
//     target：发生变动的DOM节点。
//     addedNodes：新增的DOM节点。
//     removedNodes：删除的DOM节点。
//     previousSibling：前一个同级节点，如果没有则返回null。
//     nextSibling：下一个同级节点，如果没有则返回null。
//     attributeName：发生变动的属性。如果设置了attributeFilter，则只返回预先指定的属性。
//     oldValue：变动前的值。这个属性只对attribute和characterData变动有效，如果发生childList变动，则返回null。
// 5、应用示例
//   5.1、子元素的变动
//   5.2、属性的变动
//   5.3、取代 DOMContentLoaded 事件